package local.pt.iscte.dcti.pa.view;

import javax.swing.JFrame;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Text;

/**
 * Defines the view
 * @author Simão Fernandes
 * @version %I%, %G%
 * @since 1.0
 */
public class WorksheetView extends JFrame {

	//ATTRIBUTES
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * Dynamic table
	 */
	private DynamicTable dynamicTable;
	/**
	 * Defines the sheet
	 */
	private VisibleElement[][] matriz;
	
	//CONSTRUCTORS
	
	/**
	 * Class constructor
	 * @param _numRows Number of sheet rows
	 * @param _numColumns Number of sheet Columns
	 * @param parent Implementing parent
	 */
	public WorksheetView(int _numRows, int _numColumns, Composite parent) {

		dynamicTable = new DynamicTable(parent);
		setMatriz(_numRows, _numColumns);
		dynamicTable.load(matriz);
		setTableEditor(dynamicTable.getTable());
	}
	
	//PUBLIC METHODS
	
	/**
	 * Gets a reference to the work sheet
	 * @return Work sheet reference
	 */
	public VisibleElement[][] getMatriz() {
		return this.matriz;
	}
	
	/**
	 * Adds a listener to the table
	 * @param table Reference to the table
	 * @param editor Reference to the table editor
	 */
	public void addListener(final Table table, final TableEditor editor) {

		table.addListener(SWT.MouseDown, new Listener() { // para o evento MouseDown
					/**
					 * Fired event when the mouse is down
					 */
					public void handleEvent(Event event) {
						Rectangle clientArea = table.getClientArea();
						Point pt = new Point(event.x, event.y);

						int index = table.getTopIndex();
						while (index < table.getItemCount()) { // para cada
																// linha
							boolean visible = false;
							final TableItem item = table.getItem(index);

							for (int i = 0; i < table.getColumnCount(); i++) { // para cada célula de cada linha

								Rectangle rect = item.getBounds(i);
								if (rect.contains(pt)) {
									final int column = i;
									final Text textBox = new Text(table,
											SWT.NONE); // para a textbox

									Listener textListener = getListener(item,
											index, column, textBox);

									textBox.addListener(SWT.FocusIn,
											textListener);
									textBox.addListener(SWT.FocusOut,
											textListener);
									// textBox.addListener(SWT.Traverse,
									// textListener);

									editor.setEditor(textBox, item, i);
									textBox.setText(item.getText(i));

									textBox.selectAll();
									textBox.setFocus();
									return;
								}
								if (!visible && rect.intersects(clientArea)) {
									visible = true;
								}
							}
							if (!visible)
								return;
							index++;
						}
					}
				});
	}
	
	/**
	 * Adds an observer to each cell
	 * @param theObserver Reference to the observer
	 */
	public void addObserver(java.util.Observer theObserver) {
		for (VisibleElement[] linha : matriz) {
			for (VisibleElement visibleElement : linha) {
				visibleElement.addObserver(theObserver);
			}
		}
	}
	
	/**
	 * Sets the value of a given cell
	 * @param abscisa Cell abscissa
	 * @param ordinate cell ordinate
	 * @param value cell new value
	 */
	public void setCellText(int abscisa, int ordinate, String value) {

		dynamicTable.getTable().getItem(abscisa).setText(ordinate, value);

	}
	
	//PRIVATE METHODS
	
	/**
	 * Initializes the work sheet
	 * @param numRows Number of sheet rows
	 * @param numColumns Number of sheet columns
	 */
	private void setMatriz(int numRows, int numColumns) {
		matriz = new VisibleElement[numRows][numColumns];

		for (int i = 0; i < numRows; i++) {
			for (int j = 0; j < numColumns; j++) {
				matriz[i][j] = new VisibleElement(i, j, this);
			}
		}
	}
	
	/**
	 * Sets the table editor
	 * @param table Reference to the table
	 */
	private void setTableEditor(Table table) {
		final TableEditor editor = new TableEditor(table);
		editor.horizontalAlignment = SWT.LEFT;
		editor.grabHorizontal = true;

		addListener(table, editor);
	}

	/**
	 * Sets a listener to each sheet cell
	 * @param item	Reference to TableItem
	 * @param itemIndex Item index
	 * @param columnIndex Column index
	 * @param textBox Reference to Textbox
	 * @return Reference to the Listener
	 */
	private Listener getListener(final TableItem item, final int itemIndex, final int columnIndex, final Text textBox) {
		return new Listener() {
			public void handleEvent(final Event e) {

				switch (e.type) {
				case SWT.FocusIn:
					// getFormula(itemIndex, columnIndex);
					break;

				case SWT.FocusOut:
					setValue(item, itemIndex, columnIndex, textBox);
					textBox.dispose();
					break;
				case SWT.Traverse:
					switch (e.detail) {
					case SWT.TRAVERSE_TAB_NEXT:
					case SWT.TRAVERSE_RETURN:
						setValue(item, itemIndex, columnIndex, textBox);
						// FALL THROUGH
					case SWT.TRAVERSE_ESCAPE:
						textBox.dispose();
						e.doit = false;
					}
					break;
				}
			}
		};
	}
	
	/**
	 * Sets the value of a given cell
	 * @param item Reference to TableItem instance
	 * @param rowItemIndex Row index
	 * @param columnIndex Column index
	 * @param textBox Reference to the cell text box
	 */
	private void setValue(final TableItem item, int rowItemIndex, final int columnIndex, final Text textBox) {

		String textValue = textBox.getText();
		item.setText(columnIndex, textValue);

		if (textValue != null && !textValue.isEmpty()) {
			matriz[rowItemIndex][columnIndex].setValue(textValue);
		}
	}
}
